Critter 2000!
How "Critter" by Brett Bilbrey was modified to run in AstroBASIC
March 2, 2011
By Adam Trionfo


This isn't a new version of Brett Bilbrey's "Critter."  However, I DID modify 
it so that it now runs in AstroBASIC.  I only had to modified two bytes of the 
machine language source code.  The Bally BASIC code called the Bally BASIC 
Interrupt Routine.  The AstroBASIC Interrupt Routine is in a different 
location, so of course "Critter" didn't work in the newer version of BASIC.  We 
actually knew this, but I can't recall anyone recently (that is in the past ten 
years since the start of the Bally Alley discussion group) or in any of the 
newsletters "fixing" the program for AstroBASIC.  I changed the program so that 
it makes a CALL to the AstroBASIC Interrupt Routine instead of the Bally BASIC 
routine.  Now it works without trouble.

I change the Bally BASIC version from this:

130 D=-20275;gosub C
140 D=-3296;gosub C

to this:

130 D=-563;gosub C
140 D=-3295;gosub C

Here is what the change looks like in assembly language (it makes more sense 
this way):

The Bally BASIC version had this at location $4CE3:

CALL $20B0 ; Call Bally BASIC's Interrupt Routine

It was changed to this:

CALL $21FD ; Call AstroBASIC's Interrupt Routine

The one change required two line changes in the AstroBASIC program.

For those interested, here is "Critter" in BASIC with the changes needed to run 
the program in AstroBASIC.  This code can be copied and pasted into a file and 
then run through txt2prg, then through KCS.  This will create a 300-Baud 
program.  Finally, this program can be loaded as a 300-BAUD file using the "300 
Baud to 2000 Baud Tape Converter."  You DON'T need the 300-Baud interface to do 
any of this.  Here is the program (bring back any memories, Brett?):

  10 clear ;&(15)=99
  20 A=19584;B=A;C=640
  30 D=-9741;gosub C
  40 D=19518;gosub C
  50 D=18413;gosub C
  60 D=-8130;gosub C
  70 D=3539;gosub C
  80 D=-1063;gosub C
  90 D=201;gosub C
 100 A=19680
 110 D=19683;gosub C
 120 A=19683
 130 D=-563;gosub C
 140 D=-3295;gosub C
 150 D=29677;gosub C
 160 D=19568;gosub C
 170 D=28721;gosub C
 180 D=-2740;gosub C
 190 D=-10811;gosub C
 200 D=-8731;gosub C
 210 D=-539;gosub C
 220 D=-9243;gosub C
 230 D=12828;gosub C
 240 D=19770;gosub C
 250 D=255;gosub C
 260 D=6151;gosub C
 270 D=16205;gosub C
 280 D=19768;gosub C
 290 D=19744;gosub C
 300 D=6151;gosub C
 310 D=589;gosub C
 320 D=-7683;gosub C
 330 D=-7715;gosub C
 340 D=-11807;gosub C
 350 D=-3647;gosub C
 360 D=31725;gosub C
 370 D=19568;gosub C
 380 D=-13829;gosub C
 390 A=19736
 400 D=14367;gosub C
 410 D=9293;gosub C
 420 D=2125;gosub C
 430 A=19744
 440 D=-26624;gosub C
 450 D=16384;gosub C
 460 D=0;gosub C
 470 D=2050;gosub C
 480 D=-24566;gosub C
 490 D=-30685;gosub C
 500 D=-21846;gosub C
 510 D=-22486;gosub C
 520 D=8200;gosub C
 530 D=2080;gosub C
 540 D=8200;gosub C
 550 D=0;gosub C
 560 D=-32735;gosub C
 570 D=1280;gosub C
 580 D=0;gosub C
 590 D=768;gosub C
 600 D=5;gosub C
 610 D=0;gosub C
 620 D=3;gosub C
 630 CALL B;STOP
 640 %(A)=D;A=A+2;return


For those that REALLY want to know what's going on behind the scenes, here is 
the assembly listing, you can assemble this with Zmac, if you want.  It won't 
run though, as the program needs to be entered into BASIC using, you guessed 
it, the BASIC program (above).  This will let you understand what the heck the 
BASIC program is doing (that is, if you understand Z80 assembly language and 
have looked through the "Nutting Manual").


; Critter - For the Bally Astrocade
; File Name: Crit2000.ASM
; Version 1.4 - March 2, 2011 (Modified for AstroBASIC)
; Version 1.3 - February 12, 2002
;
; This source is as it appears in the PEEK N' POKE
; manual.  It has only been changed so that it
; runs under AstroBASIC and assembles under Zmac;
; the Z80 code it generates is EXACTLY the same
; as the BASIC listing.
; When assembled, this will NOT run as a cartridge!
; Critter does not run without the first version of
; Bally BASIC; Critter does NOT run under Astro BASIC
; (it needs vector modifications).
;
; Compile with:
; zmac -i -m -o critterp.bin -x critterp.lst critterp.asm

MCALL   EQU  $06
MRET    EQU  $08
VECT    EQU  $3E

        ORG  $4C80
        DI
        EXX
        LD   A,$4C
        LD   I,A   ;Load I with page of interrupt vector
        LD   A,$E0
        OUT  ($0D),A    ; Load custom chips with line of
        EXX             ; interrupt vector
        EI
        RET

        ORG  $4CE0
        DW   $4CE3      ; Points to interrupt routine
       
        ORG  $4CE3
;       CALL $20B0      ; Call Bally BASIC interrupt routine
        CALL $21FD      ; Call AstroBASIC interrupt routine
        DI
        LD   ($4C70),SP ; Save SP
        LD   SP,$4C70   ; Move SP
        PUSH AF
        PUSH BC
        PUSH DE
        PUSH HL
        PUSH IX
        PUSH IY
        IN   A,($1C)    ; Get KN(1) value
        LD   ($4D3A),A  ; Place in vector block
        RST  $38        ; On-board call
        DB   $00        ;Routine 01 - Start Multiple Calls
        DB   MCALL+1    ; Call V Write Routine
        DW   VWRITE
        DB   VECT+1     ; Move vector (see ROM manual)
        DW   VBLOCK     ; Vector Block Address
        DW   LIMITS     ; Limit Table
        DB   MCALL+1    ; Call V Write Routine
        DW   VWRITE
        DB   $02        ; Routine 02 - End Multiple Calls
        POP  IY
        POP  IX
        POP  HL
        POP  DE
        POP  BC
        POP  AF
        LD   SP,($4C70) ; Return SP
        EI
        RET

        ORG  $4D18
VWRITE: DB   $1F        ; Routine 30 - VWRITR
        DW   $4D38      ; Vector
        DW   $4D24      ; Pattern
        DB   MRET

        ORG  $4D20
; Limit Table

LIMITS: DB   00D,152D      ; X boundaries
        DB   00D,64D       ; Y boundaries
        DB   00D,00D       ; (0,0) Position
        DB   $02,$08       ; 2 byte, 8 line pattern size

; Critter pattern
        DW   $A00A     
        DW   $8822
        DW   $AAAA
        DW   $A82A
        DW   $2008
        DW   $0820
        DW   $2008
        DW   $0000

; VECTOR BLOCK (See 'Nutting' ROM Manual, page 39-41)
VBLOCK: DB     $20     ; Magic Register value
        DB     $80     ; Vector Status
        DB     $00     ; Time Base - Holds KN(1) value
        DW     $0005   ; Delta X
        DW     $0000   ; X Position
        DB     $03     ; X Checks Mask -Bounce off walls
        DW     $0005   ; Delta Y
        DW     $0000   ; Y Position
        DB     $03     ; Y Checks Mask -Bounce off walls


I'm sure that being posted to the discussion group probably has really done 
wonders to the spacing of both the BASIC program and the assembly language 
listing.  For those that wonder if the BASIC program and the output of the 
source code match byte-for-byte with the machine language input via BASIC, they 
both match exactly (I double-checked this morning).

If anyone's eyes are boggling... don't worry.  This is actually a very short 
program.  Despite what it looks like above, the program is only 114 bytes.  
Since I'm in a REALLY geeky mood today, here is the program in machine code in 
60-column format (as it just STRETCHED if I didn't put carriage-returns):

F3D93E4CED473EE0D30DD9FBC9E34C00CDFD21F3ED73704C31704CF5C5D5
E5DDE5FDE5DB1C323A4DFF0007184D3F384D204D07184D02FDE1DDE1E1D1
C1F1ED7B704CFBC9001F384D244D08000000980040000002080AA02288AA
AA2AA8082020080820000020800005000000030500000003

It is the responsibility of the BASIC program to take these hexadecimal 
numbers, that are input in decimal form, and put them in memory where they are 
SUPPOSED to go, as these number can NOT be stringed all together starting at 
one location in memory.

Special thanks to quite a few people:

1) Thanks to Brett Bilbrey for writing this neat little graphic example program 
over thirty years ago and for sharing the assembly code in the "Peek & Poke 
Manual."

2) Thanks to Richard Degler.  Without his fully commented and disassembled 
versions of both Bally BASIC and AstroBASIC, I NEVER would have known what to 
change in "Critter's" machine language source code.

3) Thanks to the authors of the ZMac Assembler.  I was able to change the 
assembly code without wondering if I was hand-assembling the program correctly-
- not that THAT would have been a problem.  I only really just changed a call 
to a memory address. Still, I love ZMac.

4) Thanks to Ernie Sams, who in 1979, wrote "Convert Hex to Decimal" for Bally 
BASIC.  This program makes changing two hex digits to Astrocade BASIC digits a 
cinch.  For example, the machine language code for line 130 of "Critter" is 
$CD,$FD, but in Astrocade's BASIC that is -563.  Try figuring THAT out in your 
head.  Calculators won't translate this either as AstroBASIC stores numbers 
using an elegant, if esoteric, method.

5) Thanks to all the people that wrote the utilities that allow the use of a PC 
and an Astrocade together.  I wouldn't have even have TRIED to make this change 
without the 300-Baud utilities that have become available.  I wasn't even ABOUT 
to type the BASIC code... but I didn't have to.  I digitally archived the 300-
Baud version online at BallyAlley.com.  I used various programs for the Windows 
Command prompt, including: Casio Tools, KCS, prg2txt and txt2prg.  I also used 
one AstroBASIC program: "300 Baud to 2000 Baud Tape Converter."  Thanks to the 
four different authors who made these programs available!  Using these five 
utilities, I was able to:
     1. Create an editable text file from the 300-Baud program (using
        Casio Tools, KCS, and prg2txt)
     2. After editing the file, I converted it back to 300-baud (using
        txt2prg and KCS)
     3. I converted the program to 2000-baud using the conversion tool
        for AstroBASIC.  After saving the program at 2000-Baud, I ran
        it... and it worked perfectly!

For those that want to know, yes, I WILL be uploading the altered version of 
"Critter" in a 2000-Baud format so that it can be used by most folks in an 
easier to use format.

Again, thanks to everyone that made it so easy to change just two simple bytes 
in a BASIC program.  It might seem like a went through a bunch of work to make 
this happen, but really this took less than an hour from start to finish (and 
that includes a learning curve and tape loading time).

Adam
